package org.cleverframe.common.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.cleverframe.common.attributes.SessionAttributes;
import org.cleverframe.common.vo.ValidateCode;

/**
 * 用于生成验证码图片的Servlet
 * 
 * @author LiZhiWei
 * @version 2015年5月24日 上午11:08:15
 */
public class ValidateCodeServlet extends HttpServlet
{
	private static final long serialVersionUID = 1L;

	/** 验证码图片默认宽度 */
	private final int width = 70;
	/** 验证码图片默认高度 */
	private final int height = 26;

	public ValidateCodeServlet()
	{
		super();
	}

	@Override
	public void destroy()
	{
		super.destroy();
	}

	/**
	 * 在HttpSession中取得验证码字符串进行验证<br>
	 * 1.在HttpSession中取得验证码字符串<br>
	 * 2.在HttpSession中移除验证码字符串<br>
	 * 3.验证从客户端中传来的验证码，成功返回true，失败返回false<br>
	 * */
	public static boolean validate(HttpServletRequest request, String validateCode)
	{
	    ValidateCode code = (ValidateCode) request.getSession().getAttribute(SessionAttributes.VALIDATE_CODE);
		request.getSession().removeAttribute(SessionAttributes.VALIDATE_CODE);
		return validateCode.toUpperCase().equals(code.getContent());
	}

	/**
	 * 客户端GET请求<br>
	 * 1.若HttpServletRequest中有验证码参数，则验证验证码，成功返回true<br>
	 * 2.若HttpServletRequest中没有验证码参数，则返回验证码图片<br>
	 * */
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		String validateCode = request.getParameter(SessionAttributes.VALIDATE_CODE); // AJAX验证，成功返回true
		if (StringUtils.isNotBlank(validateCode))
		{
			response.getOutputStream().print(validate(request, validateCode) ? "true" : "false");
		}
		else
		{
		    createImage(request, response);
		}
	}

	/**
	 * 客户端POST请求<br>
	 * */
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
	    doGet(request, response);
	}

	/**
	 * 创建验证码图片<br>
	 * 1.把生成的验证码图片数据放到HttpServletResponse对象中<br>
	 * 2.HttpServletRequest参数"width"设置验证码图片宽度<br>
	 * 3.HttpServletRequest参数"height"设置验证码图片高度<br>
	 * 4.把生成的验证码字符串放到HttpSession对象中<br>
	 * */
	private void createImage(HttpServletRequest request, HttpServletResponse response) throws IOException
	{
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/jpeg");
		// 得到参数高，宽，都为数字时，则使用设置高宽，否则使用默认值
		int w = width;
		int h = height;
		String widthStr = request.getParameter("width");
		String heightStr = request.getParameter("height");
		if (StringUtils.isNumeric(widthStr) && StringUtils.isNumeric(heightStr))
		{
			w = NumberUtils.toInt(widthStr);
			h = NumberUtils.toInt(heightStr);
		}
		BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		// 生成背景
		createBackground(g, w, h);
		// 生成字符
		String s = createCharacter(g);
		ValidateCode validateCode = new ValidateCode(System.currentTimeMillis(), s);
		request.getSession().setAttribute(SessionAttributes.VALIDATE_CODE, validateCode);
		g.dispose();
		OutputStream out = response.getOutputStream();
		ImageIO.write(image, "JPEG", out);
		out.close();
	}

	private Color getRandColor(int fc, int bc)
	{
		int f = fc;
		int b = bc;
		Random random = new Random();
		if (f > 255)
		{
			f = 255;
		}
		if (b > 255)
		{
			b = 255;
		}
		return new Color(f + random.nextInt(b - f), f + random.nextInt(b - f), f + random.nextInt(b - f));
	}

	private void createBackground(Graphics g, int w, int h)
	{
		// 填充背景
		g.setColor(getRandColor(220, 250));
		g.fillRect(0, 0, w, h);
		// 加入干扰线条
		for (int i = 0; i < 8; i++)
		{
			g.setColor(getRandColor(40, 150));
			Random random = new Random();
			int x = random.nextInt(w);
			int y = random.nextInt(h);
			int x1 = random.nextInt(w);
			int y1 = random.nextInt(h);
			g.drawLine(x, y, x1, y1);
		}
	}

	private String createCharacter(Graphics g)
	{
        char[] codeSeq = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1',
                '2', '3', '4', '5', '6', '7', '8', '9' };
		String[] fontTypes = { "\u5b8b\u4f53", "\u65b0\u5b8b\u4f53", "\u9ed1\u4f53", "\u6977\u4f53", "\u96b6\u4e66" };
		Random random = new Random();
		StringBuilder s = new StringBuilder();
		for (int i = 0; i < 4; i++)
		{
			String r = String.valueOf(codeSeq[random.nextInt(codeSeq.length)]);// random.nextInt(10));
			g.setColor(new Color(50 + random.nextInt(100), 50 + random.nextInt(100), 50 + random.nextInt(100)));
			g.setFont(new Font(fontTypes[random.nextInt(fontTypes.length)], Font.BOLD, 26));
			g.drawString(r, 15 * i + 5, 19 + random.nextInt(8));
			// g.drawString(r, i*w/4, h-5);
			s.append(r);
		}
		return s.toString();
	}
}
